﻿using System;
using System.Data;
using System.IO;
using AgnisDAL.ServiceAgnis;
using AgnisEbmtTranslator;
using System.Threading;
using System.Windows.Forms;
using AgnisDAL;
using AgnisDAL.AGNIS_FORMSDataSetTableAdapters;

namespace TestApplication
{
    class MyTranslatorThreadHandle
    {
        private int formPublicId;
        private int ModulePublicId;
        private volatile int steps;
        private String currentEbmtDbConnectionString;
        private String currentMappingInfoConnectionString;
        private String currentAgnisStagingConnectionString;
        FormRevision myGeneratedFormRevision;
        static readonly QueriesTableAdapter qAdapter = new QueriesTableAdapter();
        // Main thread sets this event to stop worker thread:
        readonly ManualResetEvent m_EventStop;
        // Worker thread sets this event when it is stopped:
        readonly ManualResetEvent m_EventStopped;
        private string version = "1.0";  //RRA
        private int visit_id = -2;

        public MyTranslatorThreadHandle(BindingSource bs, FormTest mainForm, ManualResetEvent eventStop, ManualResetEvent eventStopped)
        {
            CurrentBindingSource = bs;
            MainForm = mainForm;
            m_EventStop = eventStop;
            m_EventStopped = eventStopped;
        }

        public BindingSource CurrentBindingSource { get; set; }

        public int ThreadSteps
        {
            get { return steps; }
            set { steps = value; }
        }

        public FormTest MainForm { get; set; }

        public bool StoreToDataBase { get; set; }

        public int NumberOfTransplantsToProcess { get; set; }

        public int AgnisPaperFormNumber { get; set; }

        public int SelectedIndex { get; set; }

        public void SetCurrentEbmtDbConnectionString(String cString)
        {
            currentEbmtDbConnectionString = cString;
        }

        public void SetCurrentMappingInfoConnectionString(String cString)
        {
            currentMappingInfoConnectionString = cString;
        }

        public void SetCurrentAgnisStagingConnectionString(String cString)
        {
            currentAgnisStagingConnectionString = cString;
        }

        private void SetFormPublicId(int _paperFormNumber)
        {
            switch (_paperFormNumber)
            {
                case 2804:
                    formPublicId = 3113592;
                    version = "1.0";
                    break;
                case 2400:
                    formPublicId = 3002012;
                    version = "2.0";
                    break;
                case 2450:
                    formPublicId = 2898108;
                    visit_id = -1; // 100 days
                    break;
                case 2900:
                    formPublicId = 2892254;
                    break;
            }
        }

        /// <summary>
        /// module of update only.
        /// </summary>
        /// <param name="_paperFormNumber"></param>
        private void SetModulePublicId(int _paperFormNumber)
        {
            switch (_paperFormNumber)
            {
                case 2804:
                    ModulePublicId = 3113597;
                    version = "1.0";
                    break;
                case 2400:
                    ModulePublicId = 3045096;
                    version = "2.0";
                    break;
                case 2450:
                    ModulePublicId = 2898447;
                    break;
                case 2900:
                    ModulePublicId = 2892372;
                    break;
            }
        }

        public void AmendStagingClientFile()
        {
            //rg 2012-05-08
            //copies a back up file of StagingClient.properties to execution path and replaces the 99999 with the correct cibmtr code for the specific centre
            const string fileSource = @"C:\agnis\StagingClient.properties";
            const string fileDestination = @"C:\agnis\grid-service\FormHandler\StagingClient.properties";
            File.WriteAllText(fileDestination, File.ReadAllText(fileSource).Replace("99999", Centre.Default.Cibmtrco));
        }

        public void ExecuteTranslationProcess()
        {
            try
            {
                if (CurrentBindingSource.Count >= NumberOfTransplantsToProcess)
                {
                    TranslatorProcess tProcess = new TranslatorProcess(currentEbmtDbConnectionString, currentMappingInfoConnectionString);
                    for (int i = 0; i < NumberOfTransplantsToProcess; i++)
                    {
                        DataRowView dView;
                        if (NumberOfTransplantsToProcess == 1 && SelectedIndex >= 0 && SelectedIndex < CurrentBindingSource.Count)
                        {
                            dView = (DataRowView)CurrentBindingSource[SelectedIndex];
                        }
                        else
                        {
                            dView = (DataRowView)CurrentBindingSource[i];
                        }
                        // celui-ci est utile pour identifier ligne à mettre à jour .
                        // int form_Id1 = 0;
                        // this variable is used for retrieving the instance_ID, from the outputFOrmRevisionID
                        int form_Id2 = 0;
                        int id = (int)dView["ID"];
                        int idaa = (int)dView["IDAA"];
                        int vIBMTRId;
                        Centre.Default.Cibmtrco = dView["CIBMTRCO"].ToString();//rg 2012-05-04 variable to capture the cibmtrco value of selected centre
                        if (i == 0)
                        {
                            AmendStagingClientFile();//rg 2012-05-08 amends the stagingClient.properties file to suit this centre
                        }
                        if (!int.TryParse(dView["CRID"].ToString(), out vIBMTRId))
                        {
                            //    throw new Exception("CRID not valid."); 
                            vIBMTRId = 0;
                        }
                        DateTime dateOfTransplant = (DateTime)dView["IDAABC"];
                        Object[] parameters = new Object[] { id, idaa, dateOfTransplant, true };
                        MainForm.Invoke(MainForm.m_DelegateRefreshStatus, new Object[] { parameters });

                        SetFormPublicId(AgnisPaperFormNumber);
                        SetModulePublicId(AgnisPaperFormNumber);
                        //RRA                        
                        //check if Form has already been sent, then get the instance_ID
                        AGNIS_FORMSDataSet dsAgnisForms = new AGNIS_FORMSDataSet();
                        cAgnisDAL.SetConnectionString(currentAgnisStagingConnectionString);
                        cAgnisDAL.LoadAgnisStagingDb(dsAgnisForms);
                        if (i == 0)
                        {
                            cAgnisDAL.UpdateInstitutionTable();// UpdateInstitutionTable();//rg 2012-05-08 updates the institution table to suit this centre
                        }
                        string instance_Id = "";
                        //TO DO : doit ajouter un filtre sur la date de transplant car on peut avoir differente greffes 
                        // if corresponding row exists in Historic table, that doesn't mean necessarely that Form has been sent.
                        // The flag that indicates that Form has been sent is the 'OUTPUT_FORM_REVISION_ID' field which is filled in by FormsNet.
                        if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDDATE_OF_HSCTFORM_NUMBERCRID(visit_id, dateOfTransplant, AgnisPaperFormNumber, vIBMTRId) != null)
                        {
                            int formRevision_id = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDDATE_OF_HSCTFORM_NUMBERCRID(visit_id, dateOfTransplant, AgnisPaperFormNumber, vIBMTRId).FORM_REVISION_ID;
                            //form_Id1 = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(visit_id, id, idaa, paperFormNumber).FORM_ID;
                            //RRA - knowing if any answer has been returned by FormsNet
                            if (qAdapter.GetOutput_FR_id(formRevision_id) != null)
                            {
                                int outputFormRevision_id = Convert.ToInt32(qAdapter.GetOutput_FR_id(formRevision_id));
                                form_Id2 = (int)dsAgnisForms.FORM_REVISION.FindByFORM_REVISION_ID(outputFormRevision_id).FORM_ID;
                                instance_Id = dsAgnisForms.FORM.FindByFORM_ID(form_Id2).INSTANCE_ID;
                            }
                            //if STATUS is REJECTED, we proceed to an initial submission (instance_id = "")
                            //if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDDATE_OF_HSCTFORM_NUMBERCRID(visit_id, dateOfTransplant, paperFormNumber, vIBMTRId).STATUS.ToLower() == "rejected")
                            //{
                            //    instance_Id = "";
                            //}
                        }
                        FormRevision myTempGeneratedFormRevision = tProcess.GenerateAgnisFormForPatient(id, idaa,
                                                                                                        dateOfTransplant, AgnisPaperFormNumber, formPublicId,
                                                                                                        decimal.Parse(version, System.Globalization.CultureInfo.CreateSpecificCulture("en-US")),
                                                                                                        TranslatorProcess.AgnisForm2450DuePeriods.HundredDays,
                                                                                                        instance_Id, vIBMTRId);
                        myGeneratedFormRevision = myTempGeneratedFormRevision;
                        steps = i;
                        if (StoreToDataBase)
                        {
                            //TO DO : Update for submission should consider the insertion into FORM , FORM_REVISION, MODULE, QUESTION tables.
                            cAgnisDAL.SendFormRevisionToDB(myTempGeneratedFormRevision, AgnisPaperFormNumber,
                                     formPublicId, visit_id, id, idaa, dateOfTransplant,
                                     vIBMTRId, instance_Id, ModulePublicId,
                                     decimal.Parse(version, System.Globalization.CultureInfo.CreateSpecificCulture("en-US")), form_Id2);
                        }
                        // Make synchronous call to main form.
                        // MainForm.RefreshStatus function runs in main thread.
                        Object[] parametersEnd = new Object[] { id, idaa, dateOfTransplant, false };
                        MainForm.Invoke(MainForm.m_DelegateRefreshStatus, new Object[] { parametersEnd });

                        // check if thread is cancelled
                        if (m_EventStop.WaitOne(0, true))
                        {
                            // clean-up operations may be placed here
                            // ...

                            // inform main thread that this thread stopped
                            m_EventStopped.Set();

                            return;
                        }
                    }
                }
                // Make synchronous call to main form
                // to inform it that thread finished
                Object[] parametersWhenFinished = new Object[] { myGeneratedFormRevision };
                MainForm.Invoke(MainForm.m_DelegateThreadFinished, new Object[] { parametersWhenFinished });
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Error occurred in ExecuteTranslationProcess() : {0}", ex.Message));
            }
        }

/*
        private FormRevision LoadFake2400FormObject(int cRID, DateTime dateOfTransplant)
        {
            //Read a xml file corresponding to form 2400.
            System.IO.FileStream fs =
             System.IO.File.OpenRead(@"D:\Mes documents\Agnis Translator Output\2400r2v2-skel-EBMT.xml");
            System.IO.StreamReader sr = new System.IO.StreamReader(fs);
            string data = sr.ReadToEnd();

            data = data.Replace("${#TestSuite#CRID}", cRID.ToString());
            data = data.Replace("${#TestSuite#DATE}", dateOfTransplant.ToShortDateString());


            XmlDocument doc = new XmlDocument();
            doc.LoadXml(data);
            //Serialize the file data using the FormRevision data type.
            XmlSerializer s = new XmlSerializer(typeof(AgnisDAL.ServiceAgnis.FormRevision));
            string xmlString = doc.OuterXml.ToString();
            byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlString);
            MemoryStream ms = new MemoryStream(buffer);
            XmlReader reader = new XmlTextReader(ms);
            Exception caught = null;

            try
            {
                object o = s.Deserialize(reader);
                AgnisDAL.ServiceAgnis.FormRevision fInput = (AgnisDAL.ServiceAgnis.FormRevision)o;
                return fInput;
            }
            catch (Exception ex)
            {
                caught = ex;
            }
            finally
            {
                reader.Close();
            }
            return null;
        }
*/

    }
}